package com.ygp.dtp.core.monitor.endpoint;

import cn.hutool.core.io.FileUtil;
import cn.hutool.system.RuntimeInfo;
import com.google.common.collect.Lists;
import com.ygp.dtp.common.dto.JvmState;
import com.ygp.dtp.common.dto.Metrics;
import com.ygp.dtp.common.dto.ThreadPoolState;
import com.ygp.dtp.core.DynamicThreadPoolRegistry;
import com.ygp.dtp.core.convert.MetricsConverter;
import com.ygp.dtp.core.thread.DynamicThreadPoolExecutor;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;

import java.util.List;

/**
 * @description: 动态线程池Endpoint监控端点扩展(参考资料 ： https : / / www.jianshu.com / p / e17e10f4ff06)
 * @motto: 代码源于生活，高于生活艺术
 * @author: zhouhengzhe
 * @date: 2022/8/9 13:37
 * @since 1.0
 **/
@Endpoint(id = "dynamic-tp")
public class DynamicThreadPoolEndpoint {
    /**
     * 可以使用@Endpoint,@WebEndpoint,@JmxEndpoint,或者EndpointWebExtension来实现HTTP方式的端点,可以是传统SpringMVC也可以是最新的Spring WebFlux
     *
     * @Endpoint相当于@WebEndpoint和@JmxEndpoint的整合。web和jmx方式都支持
     * @WebEndpoint 只会生成web的方式的端点监控
     * JmxEndpoint 只会生成Jmx的方式监控
     * @WebEndpoint 就相当于声明成一个@RestController的控制类
     * @ReadOperation GET
     * @WriteOperation POST
     * @DeleteOperation DELETE
     * <p>
     * PATH:
     * 默认的基础路径是/actuator,如果一个端点配置的路径是dynamic-tp,那么它的全路径就是/actuator/dynamic-tp
     * @Selector 的含义是让这个路径变成/actuator/dynamic-tp/{name} 我们能从路径上获取一个入参。
     * <p>
     * 自定义管理端点路径
     * management.endpoints.web.base-path = /manage
     * <p>
     * 此配置会将/actuator/dynamic-tp/{name}转换成/manage/dynamic-tp/{name}
     * <p>
     * <p>
     * <p>
     * 本端点调用接口为：/actuator/dynamic-tp
     */
    @ReadOperation
    public List<Metrics> invoke() {
        List<String> dynamicThreadPoolNames = DynamicThreadPoolRegistry.listAllDtpNames();
        List<Metrics> metricsList = Lists.newArrayList();
        dynamicThreadPoolNames.forEach(i -> {
            DynamicThreadPoolExecutor dynamicThreadPoolExecutor = DynamicThreadPoolRegistry.getExecutor(i);
            //转换对象
            ThreadPoolState threadPoolState = MetricsConverter.convert(dynamicThreadPoolExecutor);
            //把所有的线程池放进监控池子中
            metricsList.add(threadPoolState);
        });
        //获取系统的信息
        RuntimeInfo runtimeInfo = new RuntimeInfo();
        JvmState jvmState = JvmState
                .builder()
                .maxMemory(FileUtil.readableFileSize(runtimeInfo.getMaxMemory()))
                .totalMemory(FileUtil.readableFileSize(runtimeInfo.getTotalMemory()))
                .freeMemory(FileUtil.readableFileSize(runtimeInfo.getFreeMemory()))
                .usableMemory(FileUtil.readableFileSize(runtimeInfo.getUsableMemory()))
                .build();
        metricsList.add(jvmState);
        return metricsList;
    }
}
